package com.devshephard.jucks.pc;


public class syncPc {

    public static void main(String[] args) {


        Data data = new Data();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.crement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.crement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"C").start();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"D").start();
    }


}


class Data{

    public  Integer number = 0;

    public synchronized void crement() throws InterruptedException {

        /**
         * 这里切记要使用while，否则会出现虚假唤醒的问题
         * 结论：就是用if判断的话，唤醒后线程会从wait之后的代码开始运行，但是不会重新判断if条件，
         * 直接继续运行if代码块之后的代码，而如果使用while的话，也会从wait之后的代码运行，但是唤醒后会重新判断循环条件，如果不成立再执行while代码块之后的代码块，成立的话继续wait。
         * 这也就是为什么用while而不用if的原因了，因为线程被唤醒后，执行开始的地方是wait之后。
         */
        while (number != 0){
            this.wait();
        }
        number ++;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        this.notifyAll();


    }

    public synchronized void decrement() throws InterruptedException {
        while(number == 0){
            this.wait();
        }
        number --;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        this.notifyAll();

    }

}
